package com.by.gatewayhelper;

import cn.hutool.core.util.URLUtil;
import com.by.gatewayhelper.dto.GatewayContextInfo;
import com.by.redis.enums.ByRedisUtilityEnum;
import com.by.redis.support.ByRedisSupport;
import com.by.toolkit.utils.SplitterUtil;
import com.google.common.collect.Maps;
import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Component;

import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

@Slf4j
@Component
public class GatewayContext {

    @Resource
    private ByRedisSupport byRedisSupport;

    private static final String PROJECT_CODE_MAP_PROJECT_INFO = "projectCodeMapProjectInfo";

    private static final String PROJECT_ID_MAP_PROJECT_INFO = "projectIdMapProjectInfo";

    private static final String DOMAIN_MAP_PROJECT_INFO = "domainMapProjectInfo";

    private static final String WX_MA_APP_ID_MAP_PROJECT_INFO = "wxMaAppIdMapProjectInfo";

    public void putProjectCodeMapInfo(GatewayContextInfo info) {
        Integer projectCategory = info.getProjectCategory();
        String projectCode = info.getProjectCode();
        Long projectId = info.getProjectId();
        Long corpId = info.getCorpId();
        Long corpCode = info.getCorpCode();

        RedisTemplate<String, Object> redisTemplate = byRedisSupport.getJsonRedisTemplate(ByRedisUtilityEnum.COMMON);
        redisTemplate.opsForHash()
                .putAll(SplitterUtil.EN_COLON_JOINER.join(PROJECT_CODE_MAP_PROJECT_INFO, projectCode), Map.of(
                        "projectCode", projectCode,
                        "projectId", projectId,
                        "corpId", corpId,
                        "corpCode", corpCode
                ));

        redisTemplate.opsForHash()
                .putAll(SplitterUtil.EN_COLON_JOINER.join(PROJECT_ID_MAP_PROJECT_INFO, projectId), Map.of(
                        "projectCode", projectCode,
                        "projectId", projectId,
                        "corpId", corpId,
                        "corpCode", corpCode
                ));
    }

    public Map<String, String> projectCodeMapInfo(String projectCode) {
        if (StringUtils.isBlank(projectCode)) {
            return Collections.emptyMap();
        }
        String redisKey = SplitterUtil.EN_COLON_JOINER.join(PROJECT_CODE_MAP_PROJECT_INFO, projectCode);
        RedisTemplate<String, Object> redisTemplate = byRedisSupport.getJsonRedisTemplate(ByRedisUtilityEnum.COMMON);
        Map<Object, Object> entries = redisTemplate.opsForHash().entries(redisKey);
        if (entries.isEmpty()) {
            return Collections.emptyMap();
        }
        return entries.entrySet()
                .stream()
                .collect(Collectors.toMap(i -> i.getKey().toString(), i -> i.getValue().toString()));
    }

    public Map<String, String> projectIdMapInfo(String projectId) {
        if (StringUtils.isBlank(projectId)) {
            return Collections.emptyMap();
        }
        String redisKey = SplitterUtil.EN_COLON_JOINER.join(PROJECT_ID_MAP_PROJECT_INFO, projectId);
        RedisTemplate<String, Object> redisTemplate = byRedisSupport.getJsonRedisTemplate(ByRedisUtilityEnum.COMMON);
        Map<Object, Object> entries = redisTemplate.opsForHash().entries(redisKey);
        if (entries.isEmpty()) {
            return Collections.emptyMap();
        }
        return entries.entrySet()
                .stream()
                .collect(Collectors.toMap(i -> i.getKey().toString(), i -> i.getValue().toString()));
    }

    public void putMpDomainMapInfo(GatewayContextInfo info) {
        String domain = info.getDomain();
        Integer projectCategory = info.getProjectCategory();
        String projectCode = info.getProjectCode();
        Long projectId = info.getProjectId();
        Long corpId = info.getCorpId();
        Long corpCode = info.getCorpCode();
        String mpAppCode = info.getMpAppCode();

        Map<String, Object> paramMap = Maps.newHashMap(Map.of(
                "projectCode", projectCode,
                "projectId", projectId,
                "corpId", corpId,
                "corpCode", corpCode
        ));
        if (StringUtils.isNotBlank(mpAppCode)) {
            paramMap.put("mpAppCode", mpAppCode);
        }
        String host = URLUtil.toUrlForHttp(domain).getHost();
        String key = SplitterUtil.EN_COLON_JOINER.join(DOMAIN_MAP_PROJECT_INFO, host);
        RedisTemplate<String, Object> redisTemplate = byRedisSupport.getJsonRedisTemplate(ByRedisUtilityEnum.COMMON);
        redisTemplate.delete(key);
        redisTemplate.opsForHash().putAll(key, paramMap);
    }

    public void removeMpDomainMapInfo(String domain) {
        String host = URLUtil.toUrlForHttp(domain).getHost();
        RedisTemplate<String, Object> redisTemplate = byRedisSupport.getJsonRedisTemplate(ByRedisUtilityEnum.COMMON);
        String removeMpDomainMapInfoKey = SplitterUtil.EN_COLON_JOINER.join(DOMAIN_MAP_PROJECT_INFO, host);
        redisTemplate.delete(removeMpDomainMapInfoKey);
        log.info("[GatewayContext][removeMpDomainMapInfo] removeMpDomainMapInfoKey success key:[{}]", removeMpDomainMapInfoKey);
    }

    /**
     * 设置是失效时间
     *
     * @param domain
     */
    public void expireMpDomainMapInfo(String domain, Long timeout, TimeUnit timeUnit) {
        String host = URLUtil.toUrlForHttp(domain).getHost();
        RedisTemplate<String, Object> redisTemplate = byRedisSupport.getJsonRedisTemplate(ByRedisUtilityEnum.COMMON);
        String expireMpDomainMapInfoKey = SplitterUtil.EN_COLON_JOINER.join(DOMAIN_MAP_PROJECT_INFO, host);
        if (redisTemplate.hasKey(expireMpDomainMapInfoKey)) {
            redisTemplate.expire(expireMpDomainMapInfoKey, timeout, timeUnit);
            log.info("[GatewayContext][expireMpDomainMapInfo] expireMpDomainMapInfo success key:[{}] timeout:[{}] timeUnit:[{}]", expireMpDomainMapInfoKey, timeout, timeUnit);
        } else {
            log.info("[GatewayContext][expireMpDomainMapInfo] expireMpDomainMapInfoKey is null key:[{}]", expireMpDomainMapInfoKey);
        }
    }

    /**
     * 默认过期时间6个月
     *
     * @param domain
     */
    public void expireMpDomainMapInfo(String domain) {
        this.expireMpDomainMapInfo(domain, 3 * 60L, TimeUnit.DAYS);
    }

    public Map<String, String> mpDomainMapInfo(String domain) {
        if (StringUtils.isBlank(domain)) {
            return Collections.emptyMap();
        }
        String host = URLUtil.toUrlForHttp(domain).getHost();
        String redisKey = SplitterUtil.EN_COLON_JOINER.join(DOMAIN_MAP_PROJECT_INFO, host);
        RedisTemplate<String, Object> redisTemplate = byRedisSupport.getJsonRedisTemplate(ByRedisUtilityEnum.COMMON);
        Map<Object, Object> entries = redisTemplate.opsForHash().entries(redisKey);
        if (entries.isEmpty()) {
            return Collections.emptyMap();
        }
        return entries.entrySet()
                .stream()
                .collect(Collectors.toMap(i -> i.getKey().toString(), i -> i.getValue().toString()));
    }

    public void putAdminDomainMapInfo(GatewayContextInfo info) {
        String domain = info.getDomain();
        Long corpId = info.getCorpId();
        Long corpCode = info.getCorpCode();

        String host = URLUtil.toUrlForHttp(domain).getHost();

        RedisTemplate<String, Object> redisTemplate = byRedisSupport.getJsonRedisTemplate(ByRedisUtilityEnum.COMMON);
        redisTemplate.opsForHash().putAll(SplitterUtil.EN_COLON_JOINER.join(DOMAIN_MAP_PROJECT_INFO, host), Map.of(
                "corpId", corpId,
                "corpCode", corpCode
        ));
    }

    public void putAllAdminDomainMapInfo(List<GatewayContextInfo> infoList) {
        infoList.forEach(info -> {
            String domain = info.getDomain();
            Long corpId = info.getCorpId();
            Long corpCode = info.getCorpCode();
            String host = URLUtil.toUrlForHttp(domain).getHost();

            RedisTemplate<String, Object> redisTemplate = byRedisSupport.getJsonRedisTemplate(ByRedisUtilityEnum.COMMON);
            redisTemplate.opsForHash().putAll(SplitterUtil.EN_COLON_JOINER.join(DOMAIN_MAP_PROJECT_INFO, host), Map.of(
                    "corpId", corpId,
                    "corpCode", corpCode
            ));
        });
    }

    public Map<String, String> adminDomainMapInfo(String domain) {
        if (StringUtils.isBlank(domain)) {
            return Collections.emptyMap();
        }
        String host = URLUtil.toUrlForHttp(domain).getHost();
        String redisKey = SplitterUtil.EN_COLON_JOINER.join(DOMAIN_MAP_PROJECT_INFO, host);
        RedisTemplate<String, Object> redisTemplate = byRedisSupport.getJsonRedisTemplate(ByRedisUtilityEnum.COMMON);
        Map<Object, Object> entries = redisTemplate.opsForHash().entries(redisKey);
        if (entries.isEmpty()) {
            return Collections.emptyMap();
        }
        return entries.entrySet()
                .stream()
                .collect(Collectors.toMap(i -> i.getKey().toString(), i -> i.getValue().toString()));
    }

    public void putWxMaAppIdMapInfo(GatewayContextInfo info) {
        String wxMaAppId = info.getWxMaAppId();
        Long corpId = info.getCorpId();
        Long corpCode = info.getCorpCode();
        String projectCode = info.getProjectCode();
        Long projectId = info.getProjectId();

        RedisTemplate<String, Object> redisTemplate = byRedisSupport.getJsonRedisTemplate(ByRedisUtilityEnum.COMMON);
        redisTemplate.opsForHash().putAll(SplitterUtil.EN_COLON_JOINER.join(WX_MA_APP_ID_MAP_PROJECT_INFO, wxMaAppId), Map.of(
                "corpId", corpId,
                "corpCode", corpCode,
                "projectCode", projectCode,
                "projectId", projectId
        ));
    }

    public Map<String, String> wxMaAppIdMapInfo(String wxMaAppId) {
        if (StringUtils.isBlank(wxMaAppId)) {
            return Collections.emptyMap();
        }
        String redisKey = SplitterUtil.EN_COLON_JOINER.join(WX_MA_APP_ID_MAP_PROJECT_INFO, wxMaAppId);
        RedisTemplate<String, Object> redisTemplate = byRedisSupport.getJsonRedisTemplate(ByRedisUtilityEnum.COMMON);
        Map<Object, Object> entries = redisTemplate.opsForHash().entries(redisKey);
        if (entries.isEmpty()) {
            return Collections.emptyMap();
        }
        return entries.entrySet()
                .stream()
                .collect(Collectors.toMap(i -> i.getKey().toString(), i -> i.getValue().toString()));
    }

}
